package com.glacier.yuyuan.common.mybatis.interceptor;

import com.glacier.common.core.domain.BaseEntity;
import com.glacier.yuyuan.common.utils.SecurityUtils;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Signature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;

/**
 * date 2022-11-09 17:19
 * mybatis 拦截器
 * Executor (update, query, flushStatements, commit, rollback, getTransaction, close, isClosed)   拦截执行器的方法
 * ParameterHandler (getParameterObject, setParameters)	拦截参数的处理
 * ResultSetHandler (handleResultSets, handleOutputParameters)	拦截结果集的处理
 * StatementHandler (prepare, parameterize, batch, update, query) 拦截Sql语法构建的处理
 * 生效方式：
 * 一、添加注解@Component
 * 二、在mybatis-config.xml 声明plugin
 *
 * @author glacier
 * @version 1.0
 */
@Component
@Intercepts({
        @Signature(type = Executor.class, method = "update",
                args = {MappedStatement.class, Object.class,})
})
public class HandleTimeInterceptor implements Interceptor {
    private static final Logger LOGGER = LoggerFactory.getLogger(HandleTimeInterceptor.class);

    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        //invocation.getArgs()得到的结果就是args中的参数，第一个元素肯定是MappedStatement,第二个元素是我们传递给sql语句的参数
        //如果没有传递则只能得到一个元素，也就是invocation.getArgs().length的长度是1
        //如果相关的动态代理接口没有传递参数，则我们不需要对传递给sql语句的参数进行处理，直接放行动态代理接口方法
        Object[] args = invocation.getArgs();
        if (args.length == 1) {
            //只要执行了invocation.proceed()方法才会对动态代理接口进行放行，否则动态代理接口不会执行
            return invocation.proceed();
        }
        MappedStatement mappedStatement = (MappedStatement) args[0];

        if (args[1] != null && args[1] instanceof BaseEntity) {
            BaseEntity baseEntity = (BaseEntity) args[1];
            switch (mappedStatement.getSqlCommandType()) {
                case INSERT:
                    baseEntity.setCreateTime(LocalDateTime.now());
                    baseEntity.setCreateBy(SecurityUtils.getCurrentUserId());
                    LOGGER.info("新增 {}", baseEntity);
                    break;
                case UPDATE:
                    baseEntity.setUpdateTime(LocalDateTime.now());
                    baseEntity.setUpdateBy(SecurityUtils.getCurrentUserId());
                    LOGGER.info("更新 {}", baseEntity);
                    break;
                default:
                    LOGGER.info("默认 {} {}", mappedStatement.getSqlCommandType(), baseEntity);
                    break;
            }
        }
        LOGGER.info("拦截器 {} {}", mappedStatement.getSqlCommandType(), args[1]);
        return invocation.proceed();
    }
}
